/**
    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 2010  Sean Beecroft

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

 * @version 1.10 2010-01-01
 * @author Sean Beecroft
 */

package yawiki.server.application;


import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import yawiki.server.database.*;
import yawiki.server.util.StringUtility;

import java.sql.*;
import java.net.*;


public class Save extends HttpServlet {
    DbConnectionBroker broker;   
    public void init(ServletConfig config) throws ServletException {
        super.init(config); 
        // The below statement sets up a Broker with a minimun pool size of 2 connections
        // and a maximum of 5.  The log file will be created in 
        // yawiki.log and the pool connections will be
        // restarted once a day.

        try {
            broker = new DbConnectionBroker("org.postgresql.Driver",
                    "jdbc:postgresql:yawiki", "postgres", "XXXXXX", 5, 24,
                    "yawiki.log", 1.0);
        } catch (IOException e5) { 
            System.out.println(e5);
            e5.printStackTrace();
        }
    }

    public boolean acceptable(String in)
    {
	
	if( in == null ) { 
		return false;
	} 

	if( StringUtility.indexOfIgnoreCase(in, "onload") != -1 ) { 
		return false;	 
	} 

	if( StringUtility.indexOfIgnoreCase(in, "onunload") != -1 ) { 
		return false;
	} 

	if( StringUtility.indexOfIgnoreCase(in, "onclick") != -1 ) { 
		return false;
	} 

	if( StringUtility.indexOfIgnoreCase(in, "ondblclick") != -1 ) { 
		return false;
	} 

	if( StringUtility.indexOfIgnoreCase(in, "onmousedown") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "onmouseup") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "onmouseover") != -1 ) { 
		return false;
	} 
	
	if( StringUtility.indexOfIgnoreCase(in, "onmousemove") != -1 ) { 
		return false;
	} 

	if( StringUtility.indexOfIgnoreCase(in, "onmouseout") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "onfocus") != -1 ) { 
		return false;
	} 

	if( StringUtility.indexOfIgnoreCase(in, "onblur") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "onkeypress") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "onkeydown") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "onkeyup") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "onsubmit") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "onreset") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "onselect") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "onchange") != -1 ) { 
		return false;
	}  

	if( StringUtility.indexOfIgnoreCase(in, "'") != -1 ) {
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<head" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<meta" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<style" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<script" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<object" ) != -1 ) { 
		return false;
	}


	if( StringUtility.indexOfIgnoreCase(in, "<form" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<iframe" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<frame" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<body" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<title" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<HTML" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<noscript" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<IMG" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<object" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<INPUT" ) != -1 ) { 
		return false;
	}


	if( StringUtility.indexOfIgnoreCase(in, "<TEXTAREA" ) != -1 ) { 
		return false;
	}

	if( StringUtility.indexOfIgnoreCase(in, "<BUTTON" ) != -1 ) { 
		return false;
	}

	//if( StringUtility.indexOfIgnoreCase(in, "<!--" ) != -1 ) { 
	//	return false;
	//}

	
	return true;
    }
 

    public void doGet(HttpServletRequest request,
            HttpServletResponse response)
        throws IOException, ServletException {

        try { 

	    request.setCharacterEncoding("UTF-8"); 
	    
            String page =request.getParameter("page"); // "this is a big test";
            String buf =request.getParameter("buf"); // "this is the text.";

            Connection conn = null;
	    
            try { 
		page = page.replaceAll("_", " ");
                page = StringUtility.capitalize(page);
                page = URLDecoder.decode(page, "UTF-8");
		
                System.out.println("Save Page:[" + page + "]");

            } catch (Exception ex) {
                System.out.println(ex);
            }


	    System.out.println("Save called");


            	response.setContentType("text/html; charset=utf-8");
	    	BufferedWriter out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), "UTF8")); 

           
                String pageTitle = page.replaceAll("'", "&apos;");

		buf = buf.replaceAll("'", "&apos;");

		String meta = "";		
		long indx = System.currentTimeMillis();
		long hash = 0;
		
		
		conn = broker.getConnection();
            
                int con = broker.idOfConnection(conn);

                System.out.println("using:" + con);

                Statement statement = null;
                Statement versionStatement = null;
                Statement backupStatement = null;
                Statement getBackupStatement = null;
                Statement saveStatement = null;


                //System.out.println("Creating statement object");
                statement = conn.createStatement();
		versionStatement = conn.createStatement();
		backupStatement = conn.createStatement();
		getBackupStatement = conn.createStatement();
		saveStatement = conn.createStatement();
		
		if( acceptable( buf ) ) 
		{ 
			try { 
				System.out.println("Page acceptable");
				long version = System.currentTimeMillis();		
			        // save a back up. 

				String get_backup_sql = "SELECT * FROM yawiki_resource WHERE title = '" + pageTitle + "'";
				ResultSet resultSetGetBackUp = null;
				System.out.println("get backup sql:" + get_backup_sql);

				try { resultSetGetBackUp = getBackupStatement.executeQuery(get_backup_sql); } catch(Exception ex) { System.out.println("get_backup_sql failed:" + ex); } 

				System.out.println("got backup");
				if( resultSetGetBackUp != null ) { 
					if( resultSetGetBackUp.next() )
					{ 
						System.out.println("retrieve old data:");
						hash = resultSetGetBackUp.getInt("hash");
						indx = resultSetGetBackUp.getInt("indx");
						meta = resultSetGetBackUp.getString("meta");
						String data = resultSetGetBackUp.getString("data");
						
						String backup_sql = "INSERT INTO yawiki_resource_vc VALUES (" + hash + ", " + indx + ", '" + meta + "', '" + pageTitle + "', '" + data + "', " + version + ")"; 
						System.out.println("do backup:" + backup_sql);
						try { backupStatement.executeUpdate(backup_sql); } catch(Exception ex) { System.out.println("backup failed:" + ex); } 	
						System.out.println("done");
				                String sql = "UPDATE yawiki_resource SET version = " + version + ", data = '" + buf + "' WHERE title = '" + pageTitle + "'";
						System.out.println("Updating with new data...." + sql);
	                			try { statement.executeUpdate(sql); } catch(Exception ex) { System.out.println("Update failed:" + ex); } 
	
						versionStatement.close();
						getBackupStatement.close();
						backupStatement.close();
						statement.close();
	
						System.out.println("Done.");
					} else { 
						try { 
							System.out.println("Could not find existing page to backup must be new page. Save it.");
							String save_sql = "INSERT INTO yawiki_resource VALUES (0, 0, '', '" + pageTitle + "', '" + buf + "', 0)"; 
							System.out.println("do save new page:" + save_sql);
							try { saveStatement.executeUpdate(save_sql); } catch(Exception ex) { System.out.println("save failed:" + ex); } 	
						} catch(Exception ex) { 
							System.out.println("Save failed:" + ex);
						}			
					
					}
				} else { 
					System.out.println("backup is null");
					

				}

			} catch(Exception ex) { 
				System.out.println("[Unable to save]:" + ex);
				out.write("[Unable to Save]");
				out.flush();
			}
		} else { 
			out.write("[Operation Failed: Reason: Illegal JavaScript/Form/Script]");
			out.flush();
		}

                statement.close();
                statement = null;


          
            // The connection is returned to the Broker
            broker.freeConnection(conn);

            out.flush();
            out.close();

	    System.out.println("Saved OK");

        } catch (Exception ex) { 
	    System.out.println("Save threw an exception:" + ex);
            System.out.println(ex);
        }

    }

    public void doPost(HttpServletRequest request,
            HttpServletResponse response)
        throws IOException, ServletException {
        doGet(request, response);
    }
}
